﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using Citi.ReportManager.Domain;
using Citi.ReportManager.WebUi.Models;
using Citi.ReportManager.WebUi.Utils;
using Citi.SecurityHelper;

namespace Citi.ReportManager.WebUi.Controllers
{
    public class ReportController : Controller
    {
        private readonly string filesPath = ConfigurationManager.AppSettings["FilesPath"];

        public ActionResult Index(int categoryId = 0, string folder = null, int reportFolderId = 0)
        {
            var category = categoryId == 0
                    ? new Category().SelectAllActive<Category>().FirstOrDefault(x => x.ParentId == null)
                    : new Category().SelectById<Category>(categoryId);

            var report = FillFolderReportModel(folder, category);

            if (categoryId == 0)
                return View(report);

            GetFiles(report, folder, categoryId, reportFolderId);

            return View(report);
        }

        private ReportModel FillFolderReportModel(string folder, Category category)
        {
            return new ReportModel(category, folder)
            {
                Items = category.Children.Select(x => new ReportItemModel
                {
                    CategoryId = x.Id,
                    Name = x.Name,
                    Folder = true,
                    Icon = "folder.png",
                    CategoryFavorite = x.Favorites.Any(y => y.Soeid.ToUpper() == User.Identity.Name.Split(new[] { '\\' }).Last().ToUpper())
                }).ToList()
            };
        }

        private void GetFiles(ReportModel report, string folder, int categoryId, int reportFolderId = 0)
        {
            var reportFolders = reportFolderId > 0
                ? new List<ReportFolder> { new ReportFolder().SelectById<ReportFolder>(reportFolderId) }
                : new ReportFolder().GetReportFolderByCategoryId(categoryId).ToList();

            report.CurrentReportFolderId = reportFolderId;

            var reports = new List<Report>();

            reportFolders.ForEach(x =>
            {
                var reportItemModel = new ReportItemModel
                {
                    Name = x.Name,
                    Folder = true,
                    CategoryId = categoryId,
                    ReportFolderId = x.Id,
                    Icon = "folder.png"
                };

                if (string.IsNullOrWhiteSpace(folder) && x.ShowFolder && reportFolderId == 0)
                    report.Items.Add(reportItemModel);
                else
                {
                    reports.AddRange(IsCurrentFolder(folder, x));
                    GetDirectories(report, Path.Combine(filesPath, x.Id.ToString(), folder ?? string.Empty), categoryId, x.Id);
                }

                if (reportFolderId > 0)
                    report.BreadCrumbs.Insert(report.BreadCrumbs.Count - 2, reportItemModel);
            });

            reports.ForEach(x =>
                {
                    var path = Path.Combine(filesPath, x.ReportFolderId.ToString(), x.ReportName);

                    var reportName = !string.IsNullOrWhiteSpace(Path.GetExtension(Path.GetFileNameWithoutExtension(path)))
                                           ? Path.GetFileNameWithoutExtension(path)
                                           : path;

                    report.Items.Add(new ReportItemModel
                                    {
                                        Name = Path.GetFileName(reportName),
                                        PathDownload = path,
                                        Size = decimal.Divide(new FileInfo(path).Length, 1048576),
                                        Icon = IconHelper.GetFileIcon(reportName, Server.MapPath("~/Content/Images/Files")),
                                        ReportFolderId = x.ReportFolderId,
                                        CategoryId = categoryId
                                    });
                });
        }

        private static IEnumerable<Report> IsCurrentFolder(string folder, ReportFolder reportFolder)
        {
            return reportFolder.Reports.Where(y => ((string.IsNullOrEmpty(folder) && !y.ReportName.Contains(@"\")
                                    || ((!string.IsNullOrEmpty(folder) && y.ReportName.StartsWith(folder))
                                            && y.ReportName.Count(x => x == '\\') == folder.Count(x => x == '\\') + 1))));
        }

        private void GetDirectories(ReportModel report, ReportFolder reportFolder, int categoryId, string folder)
        {
            report.Items.Add(new ReportItemModel
            {
                Name = Path.GetFileName(reportFolder.FolderPath),
                PathDownload = folder,
                Folder = true,
                CategoryId = categoryId,
                ReportFolderId = reportFolder.Id,
                Icon = "folder.png"
            });
        }

        private void GetDirectories(ReportModel report, string path, int categoryId, int reportFolderId)
        {
            Directory.GetDirectories(path).ToList().ForEach(x =>
            {
                var folder = x.Replace(filesPath, string.Empty).Replace(string.Format(@"\{0}\", reportFolderId), string.Empty);
                report.Items.Add(new ReportItemModel
                {
                    Name = Path.GetFileName(x),
                    PathDownload = folder,
                    Folder = true,
                    CategoryId = categoryId,
                    ReportFolderId = reportFolderId,
                    Icon = "folder.png"
                });
            });
        }

        public ActionResult Download(int categoryId, string folder = null)
        {
            //using (ImpersonateCitiUser.GetImpersonateUser(@"lac_bra_ftools", @"lac\lac_bra_ftools", "Ferrari3k10"))
            var impersonate = (ImpersonateCitiUser.GetImpersonateUser(@"lac_bra_ftools", @"lac\lac_bra_ftools", "Ferrari3k10"));
            {
                if (categoryId == 0)
                    categoryId = new Category().SelectAllActive<Category>().FirstOrDefault(x => x.ParentId == null).Id;

                var path = Path.Combine(filesPath, categoryId.ToString(), folder ?? string.Empty);

                try
                {
                    if (!System.IO.File.Exists(path))
                        return RedirectToAction("FileNotFound", new { file = Path.GetFileName(path) });

                    var reportRequest = new ReportRequest
                    {
                        CategoryId = categoryId,
                        ReportName = folder,
                        RequestDate = DateTime.Now,
                        Soeid = User.Identity.Name.Split('\\').Last().ToUpper()
                    };
                    reportRequest.Save(reportRequest);

                    return File(path, MimeUtil.GetMimeType(Path.GetExtension(path)), Path.GetFileName(path));
                }
                catch
                {
                    return RedirectToAction("FileNotFound", new { file = folder });
                }
            }
        }

        public ActionResult FileNotFound(string file)
        {
            return View((object)file);
        }

        public void SaveFavorite(int categoryId)
        {
            var soeid = User.Identity.Name.Split(new[] { '\\' }).Last().ToUpper();
            var domain = new Favorite().SelectAll<Favorite>().FirstOrDefault(x => x.Soeid == soeid && x.CategoryId == categoryId);

            if (domain != null)
            {
                domain.Delete(domain);
                return;
            }

            domain = new Favorite { CategoryId = categoryId, Soeid = soeid };
            domain.Save(domain);
            return;
        }
    }
}
